/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "DecodeNative.h"
#include "common/sample_info.h"
#include "common/dfx/log/av_codec_sample_log.h"
#include "common/dfx/error/av_codec_sample_error.h"
#include <uv.h>
#include <string>
#include <memory>
#include <map>
#include <mutex>
#include <chrono>

#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0xFF00
#define LOG_TAG "audio_waveform_decoder_native"

// 存储实例ID和对应Decode实例的映射
std::map<std::string, std::unique_ptr<Decode>> g_decodeInstances;
std::mutex g_instancesMutex;

// 存储实例ID和对应回调上下文的映射
std::map<std::string, DecodeCallbackContext*> g_contextMap;
std::mutex g_contextMutex;

// 音频数据回调函数，用于将解码后的音频数据传递到ETS层
void AudioDataCallback(void *asyncContext) {
    uv_loop_s *loop = nullptr;
    DecodeCallbackContext *context = (DecodeCallbackContext *)asyncContext;
    
    // 首先检查上下文是否有效
    if (context == nullptr || context->env == nullptr) {
        AVCODEC_SAMPLE_LOGE("Invalid callback context");
        return;
    }
    napi_get_uv_event_loop(context->env, &loop);
    uv_work_t *work = new uv_work_t;
    work->data = context;
    
    uv_queue_work(
        loop, work, 
        [](uv_work_t *work) {},
        [](uv_work_t *work, int status) {
            DecodeCallbackContext *context = (DecodeCallbackContext *)work->data;
            
            // 再次检查上下文是否有效
            if (context == nullptr || context->env == nullptr) {
                AVCODEC_SAMPLE_LOGE("Invalid callback context in work handler");
                delete work;
                return;
            }

            
            napi_handle_scope scope = nullptr;
            // 管理napi_value的生命周期以防止内存泄漏
            napi_open_handle_scope(context->env, &scope);
            
            napi_value callback = nullptr;
            napi_get_reference_value(context->env, context->callbackRef, &callback);
            
            // 创建ArrayBuffer并填充音频数据
            size_t bufferSize = context->audioData.size();
            void *bufferData = nullptr;
            napi_value arrayBuffer = nullptr;
            napi_status stat = napi_create_arraybuffer(context->env, bufferSize, &bufferData, &arrayBuffer);
            if ((stat != napi_ok) || (bufferData == nullptr)) {
                AVCODEC_SAMPLE_LOGE("create array buffer size: %{public}u, status: %{public}u, %{public}p", bufferSize, stat, bufferData);
            }
            // 将音频数据复制到ArrayBuffer
            if (bufferData != nullptr && !context->audioData.empty()) {
                memcpy(bufferData, context->audioData.data(), bufferSize);
            }
            
            // 调用ETS层的回调函数，传递音频数据
            napi_call_function(context->env, nullptr, callback, 1, &arrayBuffer, nullptr);
            
            // 清理资源
            napi_close_handle_scope(context->env, scope);
            
            // 释放上下文资源
            if (context->end) {
                napi_delete_reference(context->env, context->callbackRef);
                context->callbackRef = nullptr;
            }
            delete context;
            delete work;
        }
    );
}
#include <random>
static std::string GenerateUuid() {
    static std::random_device rd;
    static std::mt19937_64 gen(rd());
    static std::uniform_int_distribution<uint64_t> dis;
    
    auto now = std::chrono::system_clock::now().time_since_epoch().count();
    return std::to_string(now ^ dis(gen)); // 添加随机熵
}
// 解码音频文件的方法
napi_value DecodeNative::DecodeAudio(napi_env env, napi_callback_info info) {
    SampleInfo sampleInfo;
    size_t argc = 7;  // 不需要实例ID参数
    napi_value args[7] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    // 获取参数
    napi_get_value_int32(env, args[0], &sampleInfo.inputFd);
    napi_get_value_int64(env, args[1], &sampleInfo.inputFileOffset);
    napi_get_value_int64(env, args[2], &sampleInfo.inputFileSize);
    napi_get_value_int32(env, args[3], &sampleInfo.durationMillis);
    napi_get_value_int32(env, args[4], &sampleInfo.audioSampleRate);
    napi_get_value_int32(env, args[5], &sampleInfo.expectedPoints);
    
    // 创建回调上下文
    auto asyncContext = new DecodeCallbackContext();
    asyncContext->env = env;
    // 使用时间戳生成唯一ID
    asyncContext->id = GenerateUuid();
    napi_create_reference(env, args[6], 1, &asyncContext->callbackRef);
    AVCODEC_SAMPLE_LOGD("generate ID: %{public}s,%{public}p,,audioSampleRate:%{public}d", asyncContext->id.c_str(),asyncContext, sampleInfo.audioSampleRate);
    
    // 存储上下文到映射
    {
        std::unique_lock<std::mutex> lock(g_contextMutex);
        auto it = g_contextMap.find(asyncContext->id);
        if (it != g_contextMap.end()) {
            delete it->second;
        }
        g_contextMap[asyncContext->id] = asyncContext;
    }
    
    // 设置播放完成回调
    sampleInfo.playDoneCallback = &AudioDataCallback;
    sampleInfo.playDoneCallbackData = asyncContext;
    
    // 创建并初始化新的Decode实例
    {
        std::unique_lock<std::mutex> lock(g_instancesMutex);
        auto it = g_decodeInstances.find(asyncContext->id);
        if (it != g_decodeInstances.end()) {
            it->second.reset();
        }
        
        auto decodeInstance = std::make_unique<Decode>();
        int32_t ret = decodeInstance->Init(sampleInfo);
        if (ret == AVCODEC_SAMPLE_ERR_OK) {
            ret = decodeInstance->Start();
            if (ret == AVCODEC_SAMPLE_ERR_OK) {
                g_decodeInstances[asyncContext->id] = std::move(decodeInstance);
                // 成功，返回ID字符串
                napi_value result;
                napi_create_string_utf8(env, asyncContext->id.c_str(), asyncContext->id.length(), &result);
                return result;
            } else {
                AVCODEC_SAMPLE_LOGE("Failed to start decoder: %{public}d", ret);
                // 失败，返回错误字符串
                napi_value errorResult;
                std::string errorStr = "Error: Failed to start decoder: " + std::to_string(ret);
                napi_create_string_utf8(env, errorStr.c_str(), errorStr.length(), &errorResult);
                // 清理上下文
                std::unique_lock<std::mutex> contextLock(g_contextMutex);
                g_contextMap.erase(asyncContext->id);
                return errorResult;
            }
        } else {
            AVCODEC_SAMPLE_LOGE("Failed to init decoder: %{public}d", ret);
            // 失败，返回错误字符串
            napi_value errorResult;
            std::string errorStr = "Error: Failed to init decoder: " + std::to_string(ret);
            napi_create_string_utf8(env, errorStr.c_str(), errorStr.length(), &errorResult);
            // 清理上下文
            std::unique_lock<std::mutex> contextLock(g_contextMutex);
            g_contextMap.erase(asyncContext->id);
            return errorResult;
        }
    }
    
    return nullptr;
}

// 停止解码的方法
napi_value DecodeNative::StopDecode(napi_env env, napi_callback_info info) {
    // 获取实例ID参数
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    // 如果没有提供实例ID，打印警告并返回
    if (argc < 1) {
        AVCODEC_SAMPLE_LOGE("Instance ID not provided");
        return nullptr;
    }
    
    // 转换实例ID参数
    char idBuffer[100] = {0};
    size_t idLength = 0;
    napi_status status = napi_get_value_string_utf8(env, args[0], idBuffer, sizeof(idBuffer) - 1, &idLength);
    if (status != napi_ok) {
        AVCODEC_SAMPLE_LOGE("Failed to convert instance ID to string");
        return nullptr;
    }
    
    std::string instanceId(idBuffer, idLength);
    
    // 保存当前实例的上下文以便安全释放
    DecodeCallbackContext* context = nullptr;
    std::unique_ptr<Decode> decodeInstance = nullptr;
    
    // 从映射中移除并获取上下文
    {
        std::unique_lock<std::mutex> lock(g_contextMutex);
        auto it = g_contextMap.find(instanceId);
        if (it != g_contextMap.end()) {
            context = it->second;
            g_contextMap.erase(it);
        }
    }
    
    // 从映射中移除并获取Decode实例
    {
        std::unique_lock<std::mutex> lock(g_instancesMutex);
        auto it = g_decodeInstances.find(instanceId);
        if (it != g_decodeInstances.end()) {
            // 移动实例所有权以便稍后销毁
            decodeInstance = std::move(it->second);
            // 从映射中移除
            g_decodeInstances.erase(it);
            // 注意：不需要在这里调用StartRelease，因为当decodeInstance超出作用域时会调用析构函数
            // 这样可以避免StartRelease和析构函数之间的潜在冲突
        }
    }
    return nullptr;
}

// 模块初始化函数
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor classProp[] = { 
        {"decodeNative", nullptr, DecodeNative::DecodeAudio, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"stopDecode", nullptr, DecodeNative::StopDecode, nullptr, nullptr, nullptr, napi_default, nullptr},
    };
    
    // 不再需要PluginManager::GetInstance()->Export(env, exports);，因为我们不使用视频渲染
    napi_define_properties(env, exports, sizeof(classProp) / sizeof(classProp[0]), classProp);
    return exports;
}
EXTERN_C_END

// 模块注册结构体
static napi_module DecoderModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "decode",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

// 注册模块
extern "C" __attribute__((constructor)) void RegisterDecoderModule(void) {
    napi_module_register(&DecoderModule);
}